#!/usr/bin/python
# coding:utf-8
from flask_restful import Resource, reqparse
from flask_security import login_user, auth_token_required
from flask_mail import Message
# from flask_security.decorators import roles_accepted, auth_token_required
import requests, json, random, string, time, datetime
from sqlalchemy import and_
from src.models._base import db
from src.models.user import User
from src.models.user_fun import get_user
from src.models.auth import AuthInstance, SocialAccount
from src.config.socail import SocailConfigs
from ._base import mail

__author__ = 'Methew Pan'
__create__time = '20180429'

'''
oauth2 step
step 1 send window name
|
->step 2.1 Send auth email code|| step 2.2 Send auth code
              |                             |
                  |                     |
                     |               |
                         |       |
                        step3 login
'''


# oath2 login step
# step1 Send windows name
class SendWindowName(Resource):
    def post(self):
        args = reqparse.RequestParser() \
            .add_argument('provider', type=str, location=['json', 'form'], required=True, help="授权方式不能为空") \
            .add_argument('windowName', type=str, location=['json', 'form'], required=True, help="全局内码不能为空") \
            .parse_args()
        authinst = AuthInstance(
            window_name=args['windowName'], provider=args['oathType'])
        db.session.add(authinst)
        db.session.commit()


# step2.1 Send auth email code
class SendAuthEmail(Resource):
    args = reqparse.RequestParser() \
        .add_argument('windowName', type=str, location=['json', 'form'], required=True, help="全局内码不能为空") \
        .add_argument('email', type=str, location=['json', 'form'], required=True, help="电邮地址不能为空")

    def post(self):
        self.args.parse_args()
        # 生成8位随机字符串
        # salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        # 查询用户
        try:
            user = User.query.filter_by(email=self.args['email']).first()
            authInst = db.session.query(AuthInstance).filter(and_(AuthInstance.window_name == self.args['windowName'],
                                                                  AuthInstance.provider == 'email').first())
            salt = user.get_auth_token()
            authInst.access_token = salt
            authInst.expires = 86400  # 24hours
            authInst.expires_time = datetime.datetime.now()
            db.session.commit()
        except:
            return {"error_code": 20001, "message": "数据库提交错误"}, 401
        if user:
            msg = Message(subject="Hello",
                          sender='xiaoi2008@yeah.net',
                          recipients=['402304917@qq.com'])
            msg.html = "请在此<a href=""http://localhost:3000/login?code={code}"">登录" + \
                       "或者复制http://localhost:3000/login?code={code}网址进入".format(
                           code=salt)
            mail.send(msg)
            return {"message": "登录信息已经发到登记邮箱"}, 200
        else:
            salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
            msg = Message(subject="Hello",
                          sender='xiaoi2008@yeah.net',
                          recipients=['402304917@qq.com'])
            msg.html = "请在此<a href=""http://localhost:3000/regist?code={code}"">注册" + \
                       "或者复制http://localhost:3000/regist?code={code}网址注册".format(
                           code=salt)
            mail.send(msg)
            return {"message": "注册信息已经发到填报邮箱"}, 200




# step2.2 Send auth code insert database
class SendCode(Resource):
    def post(self):
        args = reqparse.RequestParser() \
            .args.add_argument('windowName', type=str, location='json', required=True, help="window name is not null") \
            .args.add_argument('code', type=str, location='json', required=True, help="code is not null") \
            .parse_args()
        oa = AuthInstance.query.filter_by(
            window_name=args['windowName']).first()
        oa.code = args['code']
        db.session.commit()


# step3 login
class Login(Resource):
    def post(self):
        args = reqparse.RequestParser() \
            .add_argument("type", type=str, location=['form', 'json'], required=True, help="连接方式不能为空") \
            .add_argument("windowName", type=str, location=['form', 'json'], required=True, help="窗口编码不能为空") \
            .add_argument('email', type=str, location=['form', 'json']) \
            .add_argument("code", type=str, location=['form', 'json'], required=True, help="code不能为空") \
            .add_argument("redirectUri", type=str, location=['form', 'json']) \
            .parse_args()
        if args['type'] == 'email':
            if 'email' in args:
                user = get_user(args['email'])
                if user:
                    oa = db.session.query(AuthInstance). \
                        filter(
                        and_(AuthInstance.code == args['code'], AuthInstance.provider == "email")).first()
                    # oa = OAuth.query.filter(and_(OAuth.oauth_code=args['code'], OAuth.oauth_type='email')).first()
                    if oa:
                        now = time.mktime(datetime.datetime.now().timetuple())
                        lastTime = time.mktime(
                            oa.oauth_expires_time.timetuple()) + oa.oauth_expires
                        print(lastTime - now)
                        if lastTime - now >= 0:
                            user = db.session.query(User). \
                                filter(User.id == oa.oauth_userid).first()
                            if user:
                                login_user(user=user)
                                return {"message": "登录成功"}, 200
                            else:
                                return {"message": "用户不存在"}, 401
                        else:
                            return {"message": "时间超时"}, 401
                    else:
                        return {"message": "code 不存在"}, 401
                else:
                    return {"message": "用户名不存在"}, 401

            else:
                return {"message": "没有email参数"}, 401
        else:
            if 'redirectUri' in args:
                oa = AuthInstance.query.filter_by(
                    oauth_name=args['windowName']).first()
                headers = {'Accept': 'application/json',
                           'content-type': 'application/x-www-form-urlencoded'}
                payload = {'client_id': SocailConfigs[args['type']]['id'],
                           'client_secret': SocailConfigs[args['type']]['secret'],
                           'grant_type': 'authorization_code',
                           'code': oa.oauth_code,
                           'redirect_uri': args['redirectUri']
                           }
                url = SocailConfigs[args['type']]['grant']
                if SocailConfigs[args['type']]['grandMethod'] == 'get':
                    r = requests.get(url, params=payload, headers=headers)
                elif SocailConfigs[args['type']]['grandMethod'] == 'post':
                    if args['type'] == 'google':
                        r = requests.post(url, data=payload, headers=headers)
                    else:
                        r = requests.post(url, params=payload, headers=headers)
                getContent = r.json()
                if 'error' in getContent:
                    print(getContent.get('error_description'))
                    return {"message": getContent.get('error_description')}, 401
                if 'expires_in' in getContent:
                    oa.oauth_expires = getContent.get('expires_in')
                else:
                    oa.oauth_expires = 36000
                if 'access_token' in getContent:
                    oa.oauth_access_token = getContent.get('access_token')
                else:
                    return {"message": '返回值无法识别'}, 401
                if 'uid' in getContent:
                    oa.oauth_uid = getContent.get('uid')
                    user = db.session.query(User). \
                        filter(
                        and_(User.sns_id == args['uid'], User.sns_type == args['type'])).first()
                    if user:
                        login_user(user=user)
                        return {"message": "登录成功"}, 200
                    else:
                        return {"message": "用户不存在"}, 401
                else:
                    url = SocailConfigs[type]['base'] + \
                          SocailConfigs[type]['api']['me']
                    rge = requests.get(
                        url, params={'access_token': getContent.get('access_token')})
                    print(rge.text)
                db.session.commit()
            else:
                return {"message": "没有redirectUri参数"}, 401


# step5 get user information
class CheckUser(Resource):
    def post(self):
        args = reqparse.RequestParser() \
            .add_argument('windowName', type=str, location='json', required=True, help="windowName is not null") \
            .add_argument('provider', type=str, location='json', required=True, help="provider is not null") \
            .add_argument('name', type=str, location='json', required=True, help="name is not null") \
            .add_argument('code', type=str, location='json') \
            .parse_args()
        if args['type'] == 'email':
            # 如果是email登录
            user = db.session.query(User). \
                filter(and_(User.email == args['name'])).first()
            if user:
                login_user(user=user)
                return {"error_code": 0, "message": "user", "user": user.get_setup()}, 201
            else:
                return {"error_code": 10500, "message": "用户不存在", "user": None}, 401
        else:
            sc = db.session.query(SocialAccount).filter(and_(
                SocialAccount.social_id == args['name'], SocialAccount.provider == args['provider'])).first()
            if sc:
                return {"error_code": 0, "message": "user", "user": user.get_setup()}, 201
            else:
                return {"error_code": 10500, "message": "用户不存在", "user": None}, 401


# if 'error' in getContent:
#     print(getContent.get('error_description'))
# if 'expires_in' in getContent:
#     oa.oauth_expires = getContent.get('expires_in')
# if 'uid' in getContent:
#     oa.oauth_uid = getContent.get('uid')
# if 'access_token' in getContent:
#     oa.oauth_access_token = getContent.get('access_token')
#     db.session.commit()
# else:
#     return False

class Test(Resource):
    args = reqparse.RequestParser()

    @auth_token_required
    def post(self):
        self.args.parse_args()
        return 'test'


class Regist(Resource):
    @roles_accepted('admin')
    def post(self):
        args = reqparse.RequestParser() \
            .add_argument('username', type=str, location='json', required=True, help="用户名不能为空") \
            .add_argument("reigistType", type=str, location='json', required=True, help="密码不能为空") \
            .parse_args()
